<html>
<head>
<link rel="shortcut icon" href="./favicon.ico">
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="canonical" href="./Accumulator_Binary_Multiprecision_Saturating.html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Adds/subtracts the signed `increment_value` to the signed `accumulated_value`, or loads a new `load_value` to replace the `accumulated_value`. A concurrent load and increment will first load, then increment the loaded value.">
<title>Accumulator Binary Multiprecision Saturating</title>
</head>
<body>

<p class="inline bordered"><b><a href="./Accumulator_Binary_Multiprecision_Saturating.v">Source</a></b></p>
<p class="inline bordered"><b><a href="./legal.html">License</a></b></p>
<p class="inline bordered"><b><a href="./index.html">Index</a></b></p>

<h1>Multiprecision Signed Binary Accumulator, with Saturation</h1>
<p>Adds/subtracts the signed <code>increment_value</code> to the signed
 <code>accumulated_value</code>, or loads a new <code>load_value</code> to replace the
 <code>accumulated_value</code>. A concurrent load and increment will first load, then
 increment the loaded value.</p>
<p>Deasserting <code>clock_enable</code> freezes the accumulator: new increments, and
 loads, are ignored, the internal pipeline (if any) holds steady, and all
 outputs remain static.</p>
<h2>Saturation</h2>
<p>If the increment <strong>or the load</strong> would cause the accumulator to go past the
 signed minimum or maximum limits, the accumulator will saturate at the
 nearest limit value and also raise one or more of the min/max limit signals
 until the next operation. <strong>The maximum limit must be greater or equal than
 the minimum limit.</strong> If the limits are reversed, such that limit_max
 &lt; limit_min, the result will be meaningless.</p>

<pre>
`default_nettype none

module <a href="./Accumulator_Binary_Multiprecision_Saturating.html">Accumulator_Binary_Multiprecision_Saturating</a>
#(
    parameter                   WORD_WIDTH          = 0,
    parameter                   STEP_WORD_WIDTH     = 0,
    parameter                   EXTRA_PIPE_STAGES   = -1 // Use for critical paths in Accumulator
)
(
    input   wire                        clock,
    input   wire                        clock_enable,
    input   wire                        clear,

    input   wire                        increment_add_sub,  // 0/1 --> +/-
    input   wire    [WORD_WIDTH-1:0]    increment_value,
    input   wire                        increment_valid,
    output  wire                        increment_ready,

    input   wire    [WORD_WIDTH-1:0]    load_value,
    input   wire                        load_valid,
    output  wire                        load_ready,

    // These are implicitly reloaded by both the load and increment input handshakes.
    input   wire    [WORD_WIDTH-1:0]    limit_max,
    input   wire    [WORD_WIDTH-1:0]    limit_min,

    output  wire                        output_valid,
    input   wire                        output_ready,

    output  wire    [WORD_WIDTH-1:0]    accumulated_value,
    output  wire                        accumulated_value_carry_out,
    output  wire    [WORD_WIDTH-1:0]    accumulated_value_carries,
    output  wire                        accumulated_value_at_limit_max,
    output  wire                        accumulated_value_over_limit_max,
    output  wire                        accumulated_value_at_limit_min,
    output  wire                        accumulated_value_under_limit_min
);

    localparam WORD_ZERO = {WORD_WIDTH{1'b0}};
</pre>

<p>If we are <em>loading</em> then substitute the <code>accumulated_value</code> with zero, and
 the <code>increment</code> with the <code>load_value</code>.  Converting a load to an addition to
 zero prevents us from loading a value outside the given limits, which could
 really upset things in the enclosing logic, and will set the output status
 bits correctly.</p>
<p><em><code>load</code> takes priority over a concurrent <code>increment</code></em>, so a load
 concurrent with an increment will result in the accumulator holding
 <code>load_value + increment_value</code>.</p>

<pre>
    wire [WORD_WIDTH-1:0] accumulated_value_selected;
    wire [WORD_WIDTH-1:0] increment_selected;

    <a href="./Pipeline_Merge_Priority.html">Pipeline_Merge_Priority</a>
    #(
        .WORD_WIDTH     (WORD_WIDTH + WORD_WIDTH),
        .INPUT_COUNT    (2),
        .IMPLEMENTATION ("AND")
    )
    load_priority
    (
        .clock          (clock),
        .clear          (clear),

        .input_valid    ({increment_valid,                     load_valid}),
        .input_ready    ({increment_ready,                     load_ready}),
        .input_data     ({increment_value, accumulated_value,  load_value, WORD_ZERO}),

        .output_valid   (add_increment_input_valid),
        .output_ready   (add_increment_input_ready),
        .output_data    ({increment_selected, accumulated_value_selected})
    );
</pre>

<p>Apply the increment to the current accumulator value, or the load value to
 an accumulator value of zero, with saturation.</p>

<pre>
    wire add_increment_input_valid;
    wire add_increment_input_ready;

    <a href="./Adder_Subtractor_Binary_Multiprecision_Saturating.html">Adder_Subtractor_Binary_Multiprecision_Saturating</a>
    #(
        .WORD_WIDTH         (WORD_WIDTH),
        .STEP_WORD_WIDTH    (STEP_WORD_WIDTH),
        .EXTRA_PIPE_STAGES  (EXTRA_PIPE_STAGES)  // Use if predicates are critical path
    )
    add_increment
    (
        .clock              (clock),
        .clock_enable       (clock_enable),
        .clear              (clear),

        .input_valid        (add_increment_input_valid),
        .input_ready        (add_increment_input_ready),

        .limit_max          (limit_max),
        .limit_min          (limit_min),
        .add_sub            (increment_add_sub), // 0/1 -> A+B/A-B
        .A                  (accumulated_value_selected),
        .B                  (increment_selected),

        .output_valid       (output_valid),
        .output_ready       (output_ready),

        .sum                (accumulated_value),
        .carry_out          (accumulated_value_carry_out),
        .carries            (accumulated_value_carries),
        .at_limit_max       (accumulated_value_at_limit_max),
        .over_limit_max     (accumulated_value_over_limit_max),
        .at_limit_min       (accumulated_value_at_limit_min),
        .under_limit_min    (accumulated_value_under_limit_min)
    );

endmodule
</pre>

<hr>
<p><a href="./index.html">Back to FPGA Design Elements</a>
<center><a href="https://fpgacpu.ca/">fpgacpu.ca</a></center>
</body>
</html>

